package com.cloud.prac.endecrypt;

import cn.hutool.core.codec.Base64;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class RsaTest {

    private static final String ALGORITHM = "RSA";
    private static final String SIGN_ALGORITHM = "SHA256WithRSA";
    private static final Key PUBLIC_KEY;
    private static final Key PRIVATE_KEY;

    public static void main(String[] args) throws Exception {
        String str = "hello world";
        String encrypt = encrypt(str);
        log.info(encrypt);
        String decrypt = decrypt(encrypt);
        log.info(decrypt);
        String signature = getSignature(str);
        log.info(signature);
        boolean flag = verifySignature(str, signature);
        log.info("{}", flag);

    }

    /**
     * 加签
     *
     * @param str
     * @return
     * @throws Exception
     */
    private static String getSignature(String str) throws Exception {
        Signature signature = Signature.getInstance(SIGN_ALGORITHM);
        signature.initSign((PrivateKey) PRIVATE_KEY);
        // 传入原文
        signature.update(str.getBytes(StandardCharsets.UTF_8));
        // 生成签名
        byte[] sign = signature.sign();
        return Base64.encode(sign);
    }

    /**
     * 验签
     *
     * @param str
     * @param signData
     * @return
     * @throws Exception
     */
    private static boolean verifySignature(String str, String signData) throws Exception {
        Signature signature = Signature.getInstance(SIGN_ALGORITHM);
        signature.initVerify((PublicKey) PUBLIC_KEY);
        // 传入原文
        signature.update(str.getBytes(StandardCharsets.UTF_8));
        // 检验数据
        return signature.verify(Base64.decode(signData));
    }

    /**
     * 加密
     *
     * @param str
     * @return
     * @throws Exception
     */
    private static String encrypt(String str) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, PRIVATE_KEY);
        byte[] bytes = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));
        return Base64.encode(bytes);
    }

    /**
     * 解密
     *
     * @param str
     * @return
     * @throws Exception
     */
    private static String decrypt(String str) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, PUBLIC_KEY);
        byte[] decodeStr = Base64.decode(str);
        byte[] bytes = cipher.doFinal(decodeStr);
        return new String(bytes, StandardCharsets.UTF_8);
    }

    private static Map<String, Key> GeneratorKeyPair() {
        HashMap<String, Key> map = new HashMap<>(2);
        try {
            // 密钥生成器
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
            // 默认密钥长度
            keyPairGenerator.initialize(1024);
            // 生成密钥对
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();
            byte[] publicKeyEncoded = publicKey.getEncoded();
            byte[] privateKeyEncoded = privateKey.getEncoded();
            String publicKeyStr = Base64.encode(publicKeyEncoded);
            String privateKeyStr = Base64.encode(privateKeyEncoded);
            log.info(publicKeyStr);
            log.info(privateKeyStr);
            map.put("pub", publicKey);
            map.put("pri", privateKey);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return map;
    }

    static {
        final Map<String, Key> map = GeneratorKeyPair();
        PUBLIC_KEY = map.get("pub");
        PRIVATE_KEY = map.get("pri");
    }

}
